# -*- coding: utf-8 -*-

import grpc
import zmq
import json
import time

from contract_market import settings
from contract_market.base.event import Event
from .proto import message_proto_pb2, message_proto_pb2_grpc


# TODO 是否考虑回调
class RPC:
    """ """

    def __init__(self) -> None:
        """ """

    def __getattr__(self, name):
        """ """
        def do_rpc(kw=None):
            return self.do_request(name, kw)
        return do_rpc

    def do_request(self, method, kw: str = None, is_aio=False):
        """ """
        if is_aio:
            self.client = grpc.aio.insecure_channel(
                target=settings.RPC_DOMAIN, options=settings.RPC_OPTION)
        else:
            self.client = grpc.insecure_channel(
                target=settings.RPC_DOMAIN, options=settings.RPC_OPTION)
        with self.client as channel:
            # Client
            stub = message_proto_pb2_grpc.EchoProtoServerStub(channel)
            # Invoke
            nt = time.time()
            try:
                if kw:
                    response = stub.request(message_proto_pb2.GateWayRequest(
                        data=kw, method=method), timeout=settings.RPC_TIMEOUT)
                else:
                    response = stub.request(message_proto_pb2.GateWayRequest(
                        method=method), timeout=settings.RPC_TIMEOUT)
            except TypeError:
                # import pdb; pdb.set_trace()
                print("[rpc-channel] kw ", kw, method)
                return False
            except Exception as ex:
                print('[do_request]', ex, kw, method, time.time() - nt)
                # import pdb; pdb.set_trace()
                return False
        return response.data

    def _do_request(self, method, event: Event.event_data):
        data = event.data
        res = self.do_request(method, data)
        event.set_result(res)
        return res

    def send_order(self, event: Event.event_data):
        """ 
        method 的定义请参考describe方法里面的详情
        """
        method = "send_order"
        return self._do_request(method, event)

    def cancel_order(self, event: Event.event_data):
        """ """
        method = "cancel_order"
        return self._do_request(method, event)

    def describe(self, event: Event.event_data):
        """ """
        method = "describe"
        return self._do_request(method, event)

    def get_account_info(self, event: Event.event_data):
        method = "get_account_info"
        return self._do_request(method, event)

    def get_balance(self, event: Event.event_data):
        method = "get_account_balance"
        return self._do_request(method, event)

    def get_open_orders(self, event: Event.event_data):
        method = "get_account_info"
        return self._do_request(method, event)

    def to_dict(self):
        """ """
        pass


class ZMQAdaper(RPC):

    def __init__(self) -> None:
        """ """
        context = zmq.Context()
        self.socket_sender = context.socket(zmq.PUSH)  # 再设置一个socket类型PUSH推送
        self.socket_sender.connect(
            "tcp://{}:{}".format(settings.ZMQ_HOST, settings.ZMQ_PORT))  # 连接IP和端口向其推送消息

    def _do_request(self, method, event: Event.event_data):
        """ """
        data = event.data
        self.do_request(method, data)

    def do_request(self, method, kw: str = None, is_aio=False):
        """ """
        param = dict()
        param["method"] = method
        param["param"] = kw
        data = json.dumps(param)
        self.socket_sender.send_string(data)


RPCClient: RPC = RPC()  # type RPC
